package com.fanghuaiming.test.netty.c5.pipeline;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
import java.util.Scanner;
import lombok.extern.slf4j.Slf4j;

/****
 * @description:
 * @version:1.0.0
 * @author fanghuaiming
 * @data Created in 2021/9/26 下午9:03
 *
 */
@Slf4j
public class EventLoopCloseListenClient {
  public static void main(String[] args) throws InterruptedException {
      NioEventLoopGroup group = new NioEventLoopGroup();
      // 2.带有 Future,Promise 的类型都是和异步方法配套使用,用来处理结果
      ChannelFuture channelFuture = new Bootstrap()
              //如果只是channel.close()的话是不能关闭客户端的,因为 NioEventLoopGroup 中还有线程没有关闭
              .group(group)
              .channel(NioSocketChannel.class)
              .handler(new ChannelInitializer<NioSocketChannel>() {
                  @Override
                  protected void initChannel(NioSocketChannel ch) throws Exception {
                      ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                      ch.pipeline().addLast(new StringEncoder());
                  }
              })
              //1.发送连接请求
              //异步非阻塞,主线程发起了调用,真正执行连接的是 NioEventLoopGroup 中的一个线程
              .connect(new InetSocketAddress("localhost", 8080));
      //sync是阻塞方法,等待连接完成,如果少了这段代码就直接走下去了,connect线程还没有建立好连接
      //2.1 使用sync方法同步处理结果
      Channel channel = channelFuture.sync().channel();
      log.info("channel===============:{}",channel);
      new Thread(() ->{
          Scanner scanner = new Scanner(System.in);
          while (true){
              String line = scanner.nextLine();
              if("q".equals(line)){
                  channel.close();// close 也是异步操作
                  //log.info("处理关闭之后的动作");
                  break;
              }
              channel.writeAndFlush(line);
          }
      },"input").start();

      //获取 closeFuture 对象 1) 同步处理关闭 2)异步处理关闭
      ChannelFuture closeFuture = channel.closeFuture();
      closeFuture.addListener((ChannelFutureListener) future -> {
          log.info("处理关闭之后的动作");
          //优雅关闭,先拒绝接受新的任务 等待正在运行的任务执行完 再停止 注意:异常处理的时候也应该进行优雅关闭
          group.shutdownGracefully();
      });
  }
}
